/**
 * 
 */
package org.zgstudio.ddlchecker;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.xml.sax.SAXException;

/**
 * @author zhguo
 * 
 */
public class Test implements LinkCheckListener {
    private Logger logger = Logger.getLogger(Test.class.getName());
    private static PrintStream outputStream = System.out;

    public static void main(String args[]) 
            throws TooManyURLsInTaskException, SAXException, IOException, ParserConfigurationException {
        //List<Link> links = new ArrayList<Link>();
        String username, password;
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        outputStream.print("Delicious username:");
        username = br.readLine();
        outputStream.print("Delicious password:");
        password = br.readLine();
        
        Test test = new Test(username, password);
        
        while (true) {
            outputStream.print(">> ");
            String command = br.readLine().trim();
            if (command.equalsIgnoreCase("check")) {
                test.checkLinks();
            } else if (command.equalsIgnoreCase("purge")) {
                test.purgeInvalid();
            } else if (command.equalsIgnoreCase("help")) {
                outputStream.println("Commands:\n" +
                        "check - check validity of bookmarks\n" +
                        "purge - purge invalid bookmarks\n" +
                        "quit  - quit the program\n" +
                        "help  - print this doc");
            } else if (command.equalsIgnoreCase("quit")) {
                break;
            }
        }
    }
    
    private DeliciousPostsMgrV1 delMgr;
    
    public Test(String username, String password) {
        delMgr = new DeliciousPostsMgrV1(username, password);
    }
    public void checkLinks()
            throws TooManyURLsInTaskException, SAXException, IOException, ParserConfigurationException {
        Collection<Link>links = delMgr.cvtPosts2Link(delMgr.getAllPosts());
        check(links);
    }
    
    public void purgeInvalid () {
        outputStream.print("delete invalid links stored in file '" +
                resultFailFilename + "' [Y/N]? ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String answer;
        try {
            answer = br.readLine().trim();
            if (answer.equalsIgnoreCase("Y")) {
                delMgr.delPosts(new File(resultFailFilename));
            }
        } catch (IOException e) {
            outputStream.println("failed:" + e.getMessage());
        } catch (SAXException e) {
            outputStream.println("failed:" + e.getMessage());
        } catch (ParserConfigurationException e) {
            outputStream.println("failed:" + e.getMessage());
        }
    }

    private void check(Collection<Link> links) throws TooManyURLsInTaskException {
        ResultChecker rc = ResultChecker.getInstance();
        rc.registerListener(this);
        
        SimpleLinkCheck lc = new SimpleLinkCheck(rc);
        lc.checkLinks(links.toArray(new Link[] {}));
    }
    
    /* this file stores the link-checking results */
    private static String resultFilename = "linkcheck.result";
    
    /* this file stores the invalid bookmarks */
    private static String resultFailFilename = "linkcheck.fail";
    
    @Override
    public void linkCheckAllComplete() {
        logger.info("link check completed!");
        // displayNonSucc();
        try {
            writeResult2File();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void linkCheckStart() {
        logger.info("link check started!");
    }

    private void writeResult2File() throws IOException {
        File file = new File(resultFilename);
        FileWriterWithEncoding fw = new FileWriterWithEncoding(file, "UTF-8");
        IOUtils.write("---------------- succ ----------------\n", fw);
        for (Iterator<LinkCheckResult> it = succResults.iterator(); it.hasNext();) {
            String data = it.next().toString();
            IOUtils.write(data, fw);
            IOUtils.write("\n", fw);
        }
        
        File failFile = new File(resultFailFilename);
        FileWriterWithEncoding failfw = new FileWriterWithEncoding(failFile, "UTF-8");
        
        IOUtils.write("---------------- non succ ----------------\n", fw);
        for (Iterator<LinkCheckResult> it = nonSucc.iterator(); it.hasNext();) {
            LinkCheckResult result = it.next();
            String data = result.toString();
            IOUtils.write(data, fw);
            IOUtils.write("\n", fw);
            IOUtils.write(result.getLinkChecked().getUrl().toString(), failfw);
            IOUtils.write("\n", failfw);
        }
        
        IOUtils.write("---------------- stats ----------------\n", fw);
        IOUtils.write("total:"+(succResults.size()+nonSucc.size()) +
                "; succ:" + succResults.size() + 
                "; nonsucc:" + nonSucc.size()+"\n", fw);
        
        fw.close();
        failfw.close();
        
        outputStream.println("write resutls to file " + resultFilename);
        outputStream.println("invalid links are saved in file " + resultFailFilename);
    }
    
    private List<LinkCheckResult> succResults = new ArrayList<LinkCheckResult>();
    private List<LinkCheckResult> nonSucc = new ArrayList<LinkCheckResult>();
    
    public void displayNonSucc() {
        for(Iterator<LinkCheckResult> it = nonSucc.iterator(); it.hasNext();) {
            LinkCheckResult lcr = it.next();
            System.out.println("url:" + lcr.getLinkChecked().getUrl() +
                    "rc:" + lcr.getResult().getDescription());
        }
    }
    
    @Override
    public synchronized void singleLinkCheckComplete(LinkCheckResult result) {
        StringBuilder sb = new StringBuilder();
        sb.append("single link check completed.\n");
        sb.append("Link checked:").append(result.getLinkChecked().getUrl());
        sb.append(". result code:" + result.getResult().getDescription());
        
        logger.info(sb.toString());
        
        if (result.getResult() != ResultCode.SUCCEED)
            nonSucc.add(result);
        else
            succResults.add(result);
    }
}
